//package top.zywork.filter;
//
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
//import org.springframework.stereotype.Component;
//import top.zywork.common.AuthUtils;
//import top.zywork.common.DateUtils;
//import top.zywork.common.ReflectUtils;
//import top.zywork.common.WebUtils;
//import top.zywork.dos.AppAuthConfig;
//import top.zywork.dto.AppAuthDTO;
//import top.zywork.enums.AppAuthEnableEnum;
//import top.zywork.enums.ContentTypeEnum;
//import top.zywork.enums.SysConfigEnum;
//import top.zywork.service.AppAuthService;
//import top.zywork.service.SysConfigService;
//import top.zywork.vo.ResponseStatusVO;
//import top.zywork.wrapper.AppAuthHttpServletRequestWrapper;
//
//import javax.servlet.*;
//import javax.servlet.annotation.WebFilter;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//import java.util.*;
//
///**
// * AppAuthFilter过滤器类<br/>
// * <p>
// * 创建于2020-01-03<br/>
// *
// * @author 王振宇
// * @version 1.0
// */
//@Component(value = "myAppAuthFilter")
//@WebFilter(filterName = "appAuthFilter", urlPatterns = "/*")
//@Slf4j
//public class AppAuthFilter implements Filter {
//
//    private static final int TIME_UNITS_SECONDS = 60;
//    private static final int TIME_UNITS_MILLIS = 1000;
//
//    private List<String> ignoreUrlList = new ArrayList<>();
//
//    private List<String> ignoreHeaderReferList = new ArrayList<>();
//
//    private AppAuthService appAuthService;
//
//    private SysConfigService sysConfigService;
//
//    @Override
//    public void init(FilterConfig config) {
//        log.info("AppAuthFilter过滤器启动......");
//        getAppAuthFilterClass();
//    }
//
//    private void getAppAuthFilterClass() {
//        log.info("开始获取不需要授权判断的URL......");
//        List<Class<?>> classList = ReflectUtils.getClasses("top.zywork.controller", false, top.zywork.annotation.AppAuthFilter.class);
//        if (classList != null && classList.size() > 0) {
//            for (Class<?> clazz : classList) {
//                top.zywork.annotation.AppAuthFilter appAuthFilter = clazz.getDeclaredAnnotation(top.zywork.annotation.AppAuthFilter.class);
//                String[] ignoreUrls = appAuthFilter.ignoreUrls();
//                if (ignoreUrls.length > 0) {
//                    ignoreUrlList.addAll(Arrays.asList(ignoreUrls));
//                }
//                String[] ignoreHeaderRefers = appAuthFilter.ignoreHeaderRefers();
//                if (ignoreHeaderRefers.length > 0) {
//                    ignoreHeaderReferList.addAll(Arrays.asList(ignoreHeaderRefers));
//                }
//            }
//        }
//        log.info("已获取不需要授权判断的URL......");
//    }
//
//    /**
//     * 0、检查是否是认证用户，如果未认证，则直接放行进入到/auth/require请求
//     * 1、检查发起请求的appid是否存在，不存在则不合法
//     * 2、检查appid是否正确，不正确则不合法
//     * 3、检查appid对应的app是否开启了授权规则，如果未开启，则直接放行
//     * 4、检查是否配置授权规则，如果未配置，则直接放行
//     * 5、检查授权规则中是否开启授权，如果未开启，则直接放行
//     * 6、检查授权规则中是否配置过滤url，如果未配置，则直接放行
//     * @param request
//     * @param response
//     * @param chain
//     * @throws IOException
//     * @throws ServletException
//     */
//    @Override
//    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//        long currentTimestamp = DateUtils.currentTimeMillis();
//        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
//        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//        if (isIgnoreUrl(httpServletRequest)) {
//            // 如果是不需要授权的url
//            chain.doFilter(request, response);
//            return;
//        }
//        if (isIgnoreHeaderRefer(httpServletRequest)) {
//            // 如果是需要忽略的header referer
//            chain.doFilter(request, response);
//            return;
//        }
//        String appid = httpServletRequest.getHeader(AuthUtils.HEADER_PREFIX + AuthUtils.PARAM_APPID);
//        String reqUrl = httpServletRequest.getHeader(AuthUtils.HEADER_PREFIX + AuthUtils.PARAM_REQURL);
//        String timestampStr = httpServletRequest.getHeader(AuthUtils.HEADER_PREFIX + AuthUtils.PARAM_TIMESTAMP);
//        String nonceStr = httpServletRequest.getHeader(AuthUtils.HEADER_PREFIX + AuthUtils.PARAM_NONCESTR);
//        String sign = httpServletRequest.getHeader(AuthUtils.HEADER_PREFIX + AuthUtils.PARAM_SIGN);
//        if (StringUtils.isEmpty(appid)) {
//            WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，缺少appid", null));
//            return;
//        }
//        AppAuthDTO appAuthDTO = appAuthService.getAppAuthByAppid(appid);
//        if (appAuthDTO == null) {
//            WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，appid错误", null));
//            return;
//        }
//        if (appAuthDTO.getEnableAuth() == AppAuthEnableEnum.DISABLE.getValue().byteValue()) {
//            // 此appid对应的app不需要启用app授权，请求直接放行
//            chain.doFilter(request, response);
//            return;
//        }
//        AppAuthConfig appAuthConfig = sysConfigService.getByName(SysConfigEnum.APP_AUTH_CONFIG.getValue(), AppAuthConfig.class);
//        if (appAuthConfig == null) {
//            // 无appAuth配置，直接放行
//            chain.doFilter(request, response);
//            return;
//        }
//        if (!appAuthConfig.getEnableAppAuth()) {
//            // 没有启用app授权，直接放行
//            chain.doFilter(request, response);
//            return;
//        }
//        if (StringUtils.isEmpty(reqUrl) || StringUtils.isEmpty(sign) || StringUtils.isEmpty(timestampStr) || StringUtils.isEmpty(nonceStr)) {
//            WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，缺少reqUrl, timestamp, nonceStr或sign", null));
//            return;
//        }
//        try {
//            if (currentTimestamp - Long.parseLong(timestampStr) > appAuthConfig.getValidTimeInMinutes() * TIME_UNITS_SECONDS * TIME_UNITS_MILLIS) {
//                WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，超出请求有效时间", null));
//                return;
//            }
//        } catch (NumberFormatException e) {
//            WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，timestamp错误", null));
//            return;
//        }
//        String contentType = httpServletRequest.getContentType();
//        if (StringUtils.isEmpty(contentType)) {
//            // get请求没有content-type
//            if (!AuthUtils.isSignatureValid(getParamsData(appid, reqUrl, timestampStr, nonceStr, sign, httpServletRequest.getParameterMap()), appAuthDTO.getAppSecret())) {
//                WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，签名错误", null));
//                return;
//            }
//            chain.doFilter(request, response);
//        } else if (ContentTypeEnum.JSON.getValue().toLowerCase().contains(contentType.toLowerCase())) {
//            // json请求
//            AppAuthHttpServletRequestWrapper appAuthHttpServletRequestWrapper = new AppAuthHttpServletRequestWrapper(httpServletRequest);
//            Map<String, String> data = getHeaderData(appid, reqUrl, timestampStr, nonceStr, sign);
//            data.put(AuthUtils.PARAM_POST_JSON_STR, appAuthHttpServletRequestWrapper.getPostJsonStr());
//            if (!AuthUtils.isSignatureValid(data, appAuthDTO.getAppSecret())) {
//                WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，签名错误", null));
//                return;
//            }
//            chain.doFilter(appAuthHttpServletRequestWrapper, response);
//        } else if (ContentTypeEnum.FORM_URLENCODED.getValue().toLowerCase().contains(contentType.toLowerCase())) {
//            // x-www-form-urlencoded请求
//            if (!AuthUtils.isSignatureValid(getParamsData(appid, reqUrl, timestampStr, nonceStr, sign, httpServletRequest.getParameterMap()), appAuthDTO.getAppSecret())) {
//                WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，签名错误", null));
//                return;
//            }
//            chain.doFilter(request, response);
//        } else if (ContentTypeEnum.FORM_DATA.getValue().toLowerCase().contains(contentType.toLowerCase())) {
//            // multipart/form-data文件上传请求
//            if (!AuthUtils.isSignatureValid(getHeaderData(appid, reqUrl, timestampStr, nonceStr, sign), appAuthDTO.getAppSecret())) {
//                WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，签名错误", null));
//                return;
//            }
//            chain.doFilter(request, response);
//        } else {
//            WebUtils.outResponseStatusVO(httpServletResponse, ResponseStatusVO.requestInvalid("请求不合法，不支持的请求数据类型", null));
//        }
//    }
//
//    private boolean isIgnoreUrl(HttpServletRequest request) {
//        for (String ignoreUrl : ignoreUrlList) {
//            AntPathRequestMatcher matcher = new AntPathRequestMatcher(ignoreUrl);
//            if (matcher.matches(request)) {
//                return true;
//            }
//        }
//        return false;
//    }
//
//    private boolean isIgnoreHeaderRefer(HttpServletRequest request) {
//        String headerRefer = request.getHeader("Referer");
//        if (StringUtils.isEmpty(headerRefer)) {
//            return false;
//        }
//        for (String ignoreHeaderRefer : ignoreHeaderReferList) {
//            if (headerRefer.contains(ignoreHeaderRefer)) {
//                return true;
//            }
//        }
//        return false;
//    }
//
//    private Map<String, String> getHeaderData(String appid, String reqUrl, String timestamp, String nonceStr, String sign) {
//        Map<String, String> data = new HashMap<>(5);
//        data.put(AuthUtils.PARAM_APPID, appid);
//        data.put(AuthUtils.PARAM_REQURL, reqUrl);
//        data.put(AuthUtils.PARAM_TIMESTAMP, timestamp);
//        data.put(AuthUtils.PARAM_NONCESTR, nonceStr);
//        data.put(AuthUtils.PARAM_SIGN, sign);
//        return data;
//    }
//
//    /**
//     * 去获取get请求或post(x-www-form-urlencoded)请求需要用于加密的数据
//     * @param appid
//     * @param reqUrl
//     * @param timestamp
//     * @param nonceStr
//     * @param sign
//     * @param parameterMap
//     * @return
//     */
//    private Map<String, String> getParamsData(String appid, String reqUrl, String timestamp, String nonceStr, String sign, Map<String, String[]> parameterMap) {
//        Map<String, String> data = getHeaderData(appid, reqUrl, timestamp, nonceStr, sign);
//        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
//            String key = entry.getKey();
//            String[] values = entry.getValue();
//            for (String value : values) {
//                if (StringUtils.isNotEmpty(value.trim())) {
//                    if (data.containsKey(key)) {
//                        data.put(key, data.get(key) + "," + value);
//                    } else {
//                        data.put(key, value);
//                    }
//                }
//            }
//        }
//        return data;
//    }
//
//    @Override
//    public void destroy() {
//        log.info("AppAuthFilter过滤器销毁......");
//    }
//
//    @Autowired
//    public void setAppAuthService(AppAuthService appAuthService) {
//        this.appAuthService = appAuthService;
//    }
//
//    @Autowired
//    public void setSysConfigService(SysConfigService sysConfigService) {
//        this.sysConfigService = sysConfigService;
//    }
//}
